{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 加载 MNIST 数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "from keras.datasets import mnist\n",
    "\n",
    "(x_train, y_train), (x_test, y_test) = mnist.load_data('mnist/mnist.npz')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(60000, 28, 28) <class 'numpy.ndarray'>\n",
      "(60000,) <class 'numpy.ndarray'>\n"
     ]
    }
   ],
   "source": [
    "print(x_train.shape, type(x_train))\n",
    "print(y_train.shape, type(y_train))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据处理：规范化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(60000, 784) <class 'numpy.ndarray'>\n",
      "(10000, 784) <class 'numpy.ndarray'>\n"
     ]
    }
   ],
   "source": [
    "# 将图像本身从[28,28]转换为[784,]\n",
    "X_train = x_train.reshape(60000, 784)\n",
    "X_test = x_test.reshape(10000, 784)\n",
    "print(X_train.shape, type(X_train))\n",
    "print(X_test.shape, type(X_test))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将数据类型转换为float32\n",
    "X_train = X_train.astype('float32')\n",
    "X_test = X_test.astype('float32')\n",
    "# 数据归一化\n",
    "X_train /= 255\n",
    "X_test /= 255"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 统计训练数据中各标签数量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3 4 5 6 7 8 9] [5923 6742 5958 6131 5842 5421 5918 6265 5851 5949]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "label, count = np.unique(y_train, return_counts=True)\n",
    "print(label, count)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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s379+uhg+MaNG/n4449JTU0t6G6XaGFe7zt37uSKK66I3m0y1vjx42nevDktWrSgS5cu0XEHyV2Y9xvAAw88EL08GWDVqlX85S9/YdGiRSxfvpxp06ad8IytsChw5CK/B7RatWr84x//YOXKlYwZM4Zbb701WsbEiRNZvnw5q1atYseOHbz++utJ2ZeT8emnn0avaOrYsSNvvPHGCfO7O+7OgQMHcHf27t1L7dq181VXVn93ixYtSE9P59FHH2XKlCmkpKTw/vvv0717dzp37gzAggULaNmyJWlpafTq1YuXXnopelbTu3dvLr74Yj755BNSUlIYOXLkSfwHSob8vt7LlSvHkCFDePbZZ4/ZvqBfGORYJ3q/vfnmm9SvX5+mTZtG09asWUPbtm2jF4t8//vfZ/LkyXFvpwJHPuV2QC+44ILoB2PTpk35+uuvOXToEED0FDMzM5PDhw8fc+VPUWRmdOrUidatWzNixAggsk9Tp04F4PXXX2fz5s3R/OvXr+eCCy7g+9//fvT+52XKlGH48OE0b96c2rVr89FHH0WvlMpLVn/3ihUrePPNN6lSpQq9evUiIyODQ4cOsW3bNt5++20Abr31VlavXk16ejrLli2jZ8+e0XLGjx/P1q1bOXLkCBkZGfmqP6dv3enp6bRr1y6alv0Sz8WLF1O6dGkmTZoUzZ81j1KLFi147bXX8rXfRVFur/cKFSpw2WWXHTeWdDJfGJIpzHGfO3cuZ511VvT3Q4899li0nIL8dijM+23//v08/fTTDBo06JgymjVrxvz589m5cycHDx5k+vTpx7xH40VjHDnIOqBmxt13303//v2jB7Rnz57HfYBmeeONN2jVqhWnn356NK1z584sWrSIrl27ct111yVyN0JbsGABderUYfv27XTs2JFGjRoxatQofv7znzNkyBB+9KMfUbZsWQBq1arFpk2bqFq1KkuXLqVnz56sXr2aM844g+HDh/Phhx9y7rnn8rOf/YynnnqKX//613nWn+z+7jlz5hwzFvPwww8zaNAgunbtyvTp03n44YeZO3cuAEePHuWRRx6hU6dO0fzly5fn1VdfpUGDBnz++ee0bt2azp07U7ly5ULdn8JW0Nd7rNgvDBUqVKBBgwa8+OKLCdqDkxPmuF9++eVMmzbtuDJuv/12BgwYwG233ZbvesO83wYPHsz9999P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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure()\n",
    "plt.bar(label, count, width = 0.7, align='center')\n",
    "plt.title(\"Label Distribution\")\n",
    "plt.xlabel(\"Label\")\n",
    "plt.ylabel(\"Count\")\n",
    "plt.xticks(label)\n",
    "plt.ylim(0,7500)\n",
    "\n",
    "for a,b in zip(label, count):\n",
    "    plt.text(a, b, '%d' % b, ha='center', va='bottom',fontsize=10)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据处理：one-hot 编码\n",
    "\n",
    "### 几种编码方式的对比\n",
    "\n",
    "| Binary | Gray code | One-hot  |\n",
    "| ------ | --------- | -------- |\n",
    "| 000    | 000       | 00000001 |\n",
    "| 001    | 001       | 00000010 |\n",
    "| 010    | 011       | 00000100 |\n",
    "| 011    | 010       | 00001000 |\n",
    "| 100    | 110       | 00010000 |\n",
    "| 101    | 111       | 00100000 |\n",
    "| 110    | 101       | 01000000 |\n",
    "| 111    | 100       | 10000000 |\n",
    "\n",
    "### one-hot 应用\n",
    "![](https://shanelynnwebsite-mid9n9g1q9y8tt.netdna-ssl.com/wp-content/uploads/2018/01/one-hot-word-embedding-vectors.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape before one-hot encoding:  (60000,)\n",
      "Shape after one-hot encoding:  (60000, 10)\n"
     ]
    }
   ],
   "source": [
    "from keras.utils import np_utils\n",
    "\n",
    "n_classes = 10\n",
    "print(\"Shape before one-hot encoding: \", y_train.shape)\n",
    "Y_train = np_utils.to_categorical(y_train, n_classes)\n",
    "print(\"Shape after one-hot encoding: \", Y_train.shape)\n",
    "Y_test = np_utils.to_categorical(y_test, n_classes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]\n"
     ]
    }
   ],
   "source": [
    "print(y_train[0])\n",
    "print(Y_train[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使用 Keras sequential model 定义神经网络\n",
    "\n",
    "### softmax 网络层\n",
    "\n",
    "![](https://developers.google.com/machine-learning/crash-course/images/SoftmaxLayer.svg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.models import Sequential\n",
    "from keras.layers.core import Dense, Activation\n",
    "\n",
    "model = Sequential()\n",
    "model.add(Dense(512, input_shape=(784,)))\n",
    "model.add(Activation('relu'))                            \n",
    "\n",
    "model.add(Dense(512))\n",
    "model.add(Activation('relu'))\n",
    "\n",
    "model.add(Dense(10))\n",
    "model.add(Activation('softmax'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 编译模型\n",
    "\n",
    "[model.compile()](https://keras.io/models/sequential/#compile)\n",
    "\n",
    "```python\n",
    "compile(optimizer, loss=None, metrics=None, loss_weights=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练模型，并将指标保存到 history 中\n",
    "\n",
    "[model.fit()](https://keras.io/models/sequential/#fit)\n",
    "\n",
    "```python\n",
    "fit(x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0, steps_per_epoch=None, validation_steps=None)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 60000 samples, validate on 10000 samples\n",
      "Epoch 1/5\n",
      " - 10s - loss: 0.2186 - acc: 0.9353 - val_loss: 0.0935 - val_acc: 0.9709\n",
      "Epoch 2/5\n",
      " - 11s - loss: 0.0788 - acc: 0.9754 - val_loss: 0.0757 - val_acc: 0.9749\n",
      "Epoch 3/5\n",
      " - 11s - loss: 0.0494 - acc: 0.9837 - val_loss: 0.0636 - val_acc: 0.9807\n",
      "Epoch 4/5\n",
      " - 12s - loss: 0.0353 - acc: 0.9888 - val_loss: 0.0762 - val_acc: 0.9769\n",
      "Epoch 5/5\n",
      " - 11s - loss: 0.0265 - acc: 0.9910 - val_loss: 0.0724 - val_acc: 0.9786\n"
     ]
    }
   ],
   "source": [
    "history = model.fit(X_train,\n",
    "                    Y_train,\n",
    "                    batch_size=128,\n",
    "                    epochs=5,\n",
    "                    verbose=2,\n",
    "                    validation_data=(X_test, Y_test))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 可视化指标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure()\n",
    "plt.subplot(2,1,1)\n",
    "plt.plot(history.history['acc'])\n",
    "plt.plot(history.history['val_acc'])\n",
    "plt.title('Model Accuracy')\n",
    "plt.ylabel('accuracy')\n",
    "plt.xlabel('epoch')\n",
    "plt.legend(['train', 'test'], loc='lower right')\n",
    "\n",
    "plt.subplot(2,1,2)\n",
    "plt.plot(history.history['loss'])\n",
    "plt.plot(history.history['val_loss'])\n",
    "plt.title('Model Loss')\n",
    "plt.ylabel('loss')\n",
    "plt.xlabel('epoch')\n",
    "plt.legend(['train', 'test'], loc='upper right')\n",
    "plt.tight_layout()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 保存模型\n",
    "\n",
    "[model.save()](https://keras.io/getting-started/faq/#how-can-i-save-a-keras-model)\n",
    "\n",
    "You can use `model.save(filepath)` to save a Keras model into a single **HDF5 file** which will contain:\n",
    "\n",
    "- the architecture of the model, allowing to re-create the model\n",
    "- the weights of the model\n",
    "- the training configuration (loss, optimizer)\n",
    "- the state of the optimizer, allowing to resume training exactly where you left off.\n",
    "\n",
    "You can then use `keras.models.load_model(filepath)` to reinstantiate your model. load_model will also take care of compiling the model using the saved training configuration (unless the model was never compiled in the first place)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Saved trained model at ./mnist/model/keras_mnist.h5 \n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import tensorflow.gfile as gfile\n",
    "\n",
    "save_dir = \"./mnist/model/\"\n",
    "\n",
    "if gfile.Exists(save_dir):\n",
    "    gfile.DeleteRecursively(save_dir)\n",
    "gfile.MakeDirs(save_dir)\n",
    "\n",
    "model_name = 'keras_mnist.h5'\n",
    "model_path = os.path.join(save_dir, model_name)\n",
    "model.save(model_path)\n",
    "print('Saved trained model at %s ' % model_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 加载模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.models import load_model\n",
    "\n",
    "mnist_model = load_model(model_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 统计模型在测试集上的分类结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test Loss: 0.07241645678399945\n",
      "Test Accuracy: 97.86%\n",
      "Classified correctly count: 9786\n",
      "Classified incorrectly count: 214\n"
     ]
    }
   ],
   "source": [
    "loss_and_metrics = mnist_model.evaluate(X_test, Y_test, verbose=2)\n",
    "    \n",
    "print(\"Test Loss: {}\".format(loss_and_metrics[0]))\n",
    "print(\"Test Accuracy: {}%\".format(loss_and_metrics[1]*100))\n",
    "\n",
    "predicted_classes = mnist_model.predict_classes(X_test)\n",
    "\n",
    "correct_indices = np.nonzero(predicted_classes == y_test)[0]\n",
    "incorrect_indices = np.nonzero(predicted_classes != y_test)[0]\n",
    "print(\"Classified correctly count: {}\".format(len(correct_indices)))\n",
    "print(\"Classified incorrectly count: {}\".format(len(incorrect_indices)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
